﻿using System.Diagnostics;
using KinonekoSoftware.Extensions.Collections;
using KinonekoSoftware.Extensions.Ioc;
using KinonekoSoftware.Extensions.Strings.Core;
using KinonekoSoftware.Extensions.Strings.SearchModels;
using KinonekoSoftware.Extensions.Strings.SearchModels.TrieTree;
using KinonekoSoftware.Foundation.Patterns;

namespace KinonekoSoftware.ArkSpark.Services.Highlighting
{
    
    public class HighlightService<TVisual, TData> : Disposable, IHighlightService<TVisual, TData>
        where TVisual : class
        where TData : class
    {
        private readonly IGlossaryProvider<TData>                          _glossary;
        private readonly ISearchPattern<TData>                             _algorithm;
        private readonly ObservableQueue<HighlightContext<TVisual, TData>> _jobQueue;
        private readonly IHighlightVisualFactory<TVisual, TData>           _visualFactory;

        private bool _IsStart;

        public HighlightService(IHighlightVisualFactory<TVisual, TData> highlightFactory)
        {
            //
            //
            ArgumentNullException.ThrowIfNull(highlightFactory);
            
            _visualFactory = highlightFactory;
            _glossary      = Ioc.Get<IGlossaryProvider<TData>>();
            _jobQueue      = new ObservableQueue<HighlightContext<TVisual, TData>>();
            _algorithm     = new TrieTreeSearchPattern<TData>();

        }

        public void Start()
        {
            ThreadPool.QueueUserWorkItem(ThreadPoolLoop);

            _IsStart = true;
        }

        public void Stop()
        {
            _IsStart = false;
        }

        private IList<MatchResult<TData>> Match(string input)
        {
            if (_glossary.Version != _algorithm.Version)
            {
                _algorithm.Build(_glossary);
            }

            return _algorithm.Match(input);
        }


        private void ThreadPoolLoop(object state)
        {
            while (_IsStart)
            {
                if (_jobQueue.Count > 0)
                {
                    //
                    //
                    if (_jobQueue.TryDequeue(out var job))
                    {

                        try
                        {

                            //
                            //
                            var results = Match(job.Text);

                            if (results is null)
                            {
                                continue;
                            }

                            //
                            //
                            _visualFactory?.BuildHighlightVisuals(job, results);
                        }
                        catch
                        {
                            Debug.WriteLine("Job Exception");
                        }
                    }
                }
                else
                {
                    Thread.Sleep(50);
                }
            }
        }
    }
}